package com.xz.simplerpc.rpc;


import com.xz.simplerpc.constants.Constants;
import com.xz.simplerpc.extension.ExtensionLoader;
import com.xz.simplerpc.extension.URL;
import com.xz.simplerpc.rpc.api.Invoker;
import com.xz.simplerpc.rpc.api.Protocol;
import com.xz.simplerpc.rpc.api.ServiceClassHolder;
import com.xz.simplerpc.rpc.proxy.JdkProxyFactory;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetAddress;

/**
 * Created by fingal on 2018/1/7.
 */
public class ServiceConfig<T> {
    private static final Logger logger = LoggerFactory.getLogger(ServiceConfig.class);

    private Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();

    private JdkProxyFactory jdkProxyFactory = new JdkProxyFactory();

    private RegistryConfig registryConfig;

    private ProtocolConfig protocolConfig;

    private int port;

    private Class<T> interfaceClass;

    private T ref;

    public ProtocolConfig getProtocolConfig() {
        return protocolConfig;
    }

    public void setProtocolConfig(ProtocolConfig protocolConfig) {
        this.protocolConfig = protocolConfig;
    }

    public RegistryConfig getRegistryConfig() {
        return registryConfig;
    }

    public void setRegistryConfig(RegistryConfig registryConfig) {
        this.registryConfig = registryConfig;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public Class<?> getInterfaceClass() {
        return interfaceClass;
    }

    public void setInterfaceClass(Class<T> interfaceClass) {
        this.interfaceClass = interfaceClass;
    }

    public T getRef() {
        return ref;
    }

    public void setRef(T ref) {
        this.ref = ref;
    }

    public void export() {
        ServiceClassHolder.getInstance().pushServiceClass(ref.getClass());
        URL providerUrl = getProviderUrl();
        if(registryConfig!=null && StringUtils.isNoneBlank(registryConfig.getAddress())) {
            URL registryUrl = URL.valueOf(registryConfig.getAddress())
                    .setServiceInterface(interfaceClass.getName())
                    .addParameter(Constants.SIDE_KEY, Constants.PROVIDER_SIDE)
                    .addParameterAndEncoded(Constants.EXPORT_KEY, providerUrl.toFullString())
                    .addParameter(Constants.PROTOCOL_KEY, protocolConfig.getName());
            Invoker<T> invoker = jdkProxyFactory.getInvoker(ref, interfaceClass, registryUrl);
            protocol.export(invoker, registryUrl);
        } else {
            Invoker<T> invoker = jdkProxyFactory.getInvoker(ref, interfaceClass, providerUrl);
            protocol.export(invoker, providerUrl);
        }
    }

    private URL getProviderUrl() {
        try {
            String address = InetAddress.getLocalHost().getHostAddress();
            return new URL(protocolConfig.getName(), address, port, interfaceClass.getCanonicalName());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
